import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:math' as math;
import 'main.dart';

//图像绘制模块相对独立，所以直接从main.dart中分离以减小main.dart的复杂度
class TimelinePainter extends CustomPainter {
  final SpaxisManager manager;
  final bool isEditMode;
  final Function(SpaxisEvent) onEventTap;
  final int trackCount;

  TimelinePainter({
    required this.manager,
    required this.isEditMode,
    required this.onEventTap,
    this.trackCount = 1,
  });

  /// 为事件分配轨道，避免重叠，返回事件ID到轨道号的映射
  /// 分配算法：
  /// 1. 先对事件按 startTime、id 排序，保证顺序唯一。
  /// 2. 依次遍历事件，为每个事件分配最早可用轨道（不与已分配事件重叠）。
  /// 3. 只要事件列表和轨道数不变，分配结果就不变。
  Map<String, int> _assignEventTracks(List<SpaxisEvent> events, double canvasWidth) {
    final sorted = List<SpaxisEvent>.from(events)
      ..sort((a, b) {
        final cmp = a.startTime.compareTo(b.startTime);
        if (cmp != 0) return cmp;
        return a.id.compareTo(b.id);
      });
    final List<DateTime?> trackEndTimes = List.filled(this.trackCount, null);
    final Map<String, int> assignments = {};
    for (final event in sorted) {
      int assignedTrack = 0;
      for (int t = 0; t < this.trackCount; t++) {
        final lastEnd = trackEndTimes[t];
        final eventStart = event.startTime;
        final eventEnd = event.endTime ?? event.startTime.add(Duration(minutes: 1));
        if (lastEnd == null || !eventStart.isBefore(lastEnd)) {
          assignedTrack = t;
          trackEndTimes[t] = eventEnd;
          break;
        }
      }
      assignments[event.id] = assignedTrack;
    }
    return assignments;
  }

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint();

    // 绘制背景渐变
    final gradient = LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      colors: [Colors.grey[50]!, Colors.white, Colors.grey[50]!],
    );

    paint.shader =
        gradient.createShader(Rect.fromLTWH(0, 0, size.width, size.height));
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);

    // 绘制主时间轴
    _drawMainAxis(canvas, size);

    // 绘制时间刻度
    _drawTimeMarkers(canvas, size);

    // 绘制事件
    _drawEvents(canvas, size);

    // 绘制当前时间指示器
    _drawCurrentTimeIndicator(canvas, size);
  }

  void _drawMainAxis(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.grey[600]!
      ..strokeWidth = 3
      ..strokeCap = StrokeCap.round;

    final y = size.height / 2;

    // 绘制无限延伸的带状轴
    final path = Path();
    path.moveTo(-50, y);
    path.lineTo(size.width + 50, y);
    canvas.drawPath(path, paint);

    // 绘制轴的延伸效果
    final gradientPaint = Paint()
      ..shader = LinearGradient(
        colors: [
          Colors.grey[300]!,
          Colors.grey[500]!,
          Colors.grey[500]!,
          Colors.grey[300]!
        ],
        stops: [0.0, 0.1, 0.9, 1.0],
      ).createShader(Rect.fromLTWH(-50, y - 2, size.width + 100, 4));

    canvas.drawRect(
        Rect.fromLTWH(-50, y - 2, size.width + 100, 4), gradientPaint);
  }

  void _drawTimeMarkers(Canvas canvas, Size size) {
    final currentUnit = manager.currentTimeUnit;

    // 根据缩放级别调整刻度密度
    final tickDensity = _calculateTickDensity(manager.zoomLevel, size.width);
    final baseInterval = _getBaseInterval(currentUnit);
    final majorInterval =
        _calculateOptimalInterval(baseInterval, size.width, tickDensity);

    // 计算起始时间，对齐到刻度
    final alignedStart =
        _alignTimeToInterval(manager.viewportStart, majorInterval, currentUnit);

    // 绘制时间上下文（左下角的大字前缀）
    _drawTimeContext(canvas, size, currentUnit);

    // 绘制主刻度和标签
    _drawMajorMarkers(canvas, size, alignedStart, majorInterval, currentUnit);

    // 绘制次刻度
    if (manager.zoomLevel > 1) {
      _drawMinorMarkers(canvas, size, alignedStart, majorInterval, currentUnit);
    }
  }

  void _drawTimeContext(Canvas canvas, Size size, TimeUnitConfig unit) {
    // 获取屏幕中央对应的时间
    final centerTime = manager.xToTime(size.width / 2, size.width);
    final contextInfo = _getTimeContextInfo(centerTime, unit);

    if (contextInfo.isEmpty) return;

    final contextStyle = TextStyle(
      color: Colors.grey[400]!.withOpacity(0.6),
      fontSize: _getContextFontSize(unit),
      fontWeight: FontWeight.bold, // 加粗
      height: 1.2,
    );

    final textPainter = TextPainter(
      text: TextSpan(text: contextInfo, style: contextStyle),
      textDirection: ui.TextDirection.ltr,
      textAlign: TextAlign.left,
    );

    textPainter.layout();

    // 绘制在左下角，留出适当边距
    final contextPosition = Offset(20, size.height - textPainter.height - 20);

    textPainter.paint(canvas, contextPosition);
  }

  // 获取时间上下文信息
  String _getTimeContextInfo(DateTime centerTime, TimeUnitConfig unit) {
    switch (unit.unit) {
      case TimeUnit.decade:
        final century = ((centerTime.year - 1) ~/ 100) + 1;
        return '${century}世纪';
      case TimeUnit.year:
        final decade = (centerTime.year ~/ 10) * 10;
        return '${decade}年代';
      case TimeUnit.month:
        return '${centerTime.year}年';
      case TimeUnit.day:
        return '${centerTime.year}年\n${centerTime.month}月';
      case TimeUnit.hour:
        return '${centerTime.year}.${centerTime.month}.${centerTime.day}';
      case TimeUnit.minute:
        return '${centerTime.year}.${centerTime.month}.${centerTime.day}\n${centerTime.hour}时';
      default:
        return '';
    }
  }

  double _getContextFontSize(TimeUnitConfig unit) {
    switch (unit.unit) {
      case TimeUnit.decade:
        return 48;
      case TimeUnit.year:
        return 42;
      case TimeUnit.month:
        return 36;
      case TimeUnit.day:
        return 32;
      case TimeUnit.hour:
        return 28;
      case TimeUnit.minute:
        return 24;
      default:
        return 24;
    }
  }

  // 计算刻度密度
  double _calculateTickDensity(double zoomLevel, double canvasWidth) {
    // 根据缩放级别动态调整刻度密度
    if (zoomLevel < 0.5) return 0.5; // 低缩放，少刻度
    if (zoomLevel < 2) return 1.0; // 正常密度
    if (zoomLevel < 10) return 1.5; // 中等密度
    return 2.0; // 高缩放，多刻度
  }

  Duration _getBaseInterval(TimeUnitConfig unit) {
    switch (unit.unit) {
      case TimeUnit.decade:
        return Duration(days: 3652); // 10年
      case TimeUnit.year:
        return Duration(days: 365); // 1年
      case TimeUnit.month:
        return Duration(days: 30); // 1月
      case TimeUnit.day:
        return Duration(days: 1); // 1日
      case TimeUnit.hour:
        return Duration(hours: 1); // 1时
      case TimeUnit.minute:
        return Duration(minutes: 1); // 1分
    }
  }

  Duration _calculateOptimalInterval(
      Duration baseInterval, double canvasWidth, double density) {
    // 只允许标准单位，不允许倍数
    return baseInterval;
  }

  DateTime _alignTimeToInterval(
      DateTime time, Duration interval, TimeUnitConfig unit) {
    switch (unit.unit) {
      case TimeUnit.decade:
        final year = (time.year ~/ 10) * 10;
        return DateTime(year, 1, 1);

      case TimeUnit.year:
        final years = interval.inDays ~/ 365;
        final alignedYear = (time.year ~/ years) * years;
        return DateTime(alignedYear, 1, 1);

      case TimeUnit.month:
        return DateTime(time.year, time.month, 1);

      case TimeUnit.day:
        return DateTime(time.year, time.month, time.day);

      case TimeUnit.hour:
        return DateTime(time.year, time.month, time.day, time.hour);

      case TimeUnit.minute:
        return DateTime(
            time.year, time.month, time.day, time.hour, time.minute);
    }
  }

  // 计算主刻度透明度，随当前时间单位的缩放区间平滑渐变
  double _getMajorTickAlpha(double zoomLevel, double minZoom, double maxZoom) {
    final double fadeIn = minZoom * 0.5;
    final double fadeOut = maxZoom * 2.0;
    // 最小透明度提升到0.35，最大为1.0
    if (zoomLevel <= fadeIn) return 0.35;
    if (zoomLevel >= fadeOut) return 1.0;
    return (0.35 + ((zoomLevel - fadeIn) / (fadeOut - fadeIn)) * (1.0 - 0.35)).clamp(0.35, 1.0);
  }

  // 修改主刻度绘制，主刻度线和标签都用透明度渐变，区间随当前时间单位变化
  void _drawMajorMarkers(Canvas canvas, Size size, DateTime startTime,
      Duration interval, TimeUnitConfig unit) {
    final double majorAlpha = _getMajorTickAlpha(
      manager.zoomLevel, unit.minZoomLevel, unit.maxZoomLevel);
    if (majorAlpha < 0.01) return; // 透明度极低时不绘制
    final paint = Paint()
      ..color = Colors.grey[700]!.withOpacity(majorAlpha)
      ..strokeWidth = 2;

    final textStyle = TextStyle(
      color: Colors.grey[800]!.withOpacity(majorAlpha),
      fontSize: 13,
      fontWeight: FontWeight.w500,
    );

    DateTime current = startTime;
    final endTime = manager.viewportEnd.add(interval);

    // 防止无限循环
    int iterations = 0;
    const maxIterations = 100;

    while (current.isBefore(endTime) && iterations < maxIterations) {
      final x = manager.timeToX(current, size.width);

      if (x >= -100 && x <= size.width + 100) {
        // 绘制主刻度线
        // 只绘制下半部分主刻度线
        canvas.drawLine(
          Offset(x, size.height / 2),
          Offset(x, size.height / 2 + 25),
          paint,
        );

        // 绘制简化的时间标签（去掉前缀）
        final label = _formatSimplifiedTimeLabel(current, unit);
        final textPainter = TextPainter(
          text: TextSpan(text: label, style: textStyle),
          textDirection: ui.TextDirection.ltr,
        );
        textPainter.layout();

        // 绘制标签背景
        final labelRect = Rect.fromCenter(
          center: Offset(x, size.height / 2 + 40),
          width: textPainter.width + 12,
          height: textPainter.height + 6,
        );

        final bgPaint = Paint()
          ..color = Colors.white.withOpacity(0.95 * majorAlpha)
          ..style = PaintingStyle.fill;

        final borderPaint = Paint()
          ..color = Colors.grey[300]!.withOpacity(majorAlpha)
          ..style = PaintingStyle.stroke
          ..strokeWidth = 1;

        canvas.drawRRect(
          RRect.fromRectAndRadius(labelRect, Radius.circular(6)),
          bgPaint,
        );
        canvas.drawRRect(
          RRect.fromRectAndRadius(labelRect, Radius.circular(6)),
          borderPaint,
        );

        textPainter.paint(
          canvas,
          Offset(x - textPainter.width / 2, size.height / 2 + 32),
        );
      }

      current = _addInterval(current, interval, unit);
      iterations++;
    }
  }

  // 新的简化时间标签格式化（去掉重复前缀）
  String _formatSimplifiedTimeLabel(DateTime time, TimeUnitConfig unit) {
    switch (unit.unit) {
      case TimeUnit.decade:
        return '${time.year}'; // 只显示年份

      case TimeUnit.year:
        return '${time.year}'; // 只显示年份

      case TimeUnit.month:
        return '${time.month}月'; // 只显示月份

      case TimeUnit.day:
        return '${time.day}日'; // 只显示日期

      case TimeUnit.hour:
        return '${time.hour}时'; // 只显示小时

      case TimeUnit.minute:
        return '${time.minute.toString().padLeft(2, '0')}分'; // 只显示分钟
    }
  }

  // 计算小刻度透明度，随缩放平滑变化
  double _getMinorTickAlpha(double zoomLevel) {
    const double minZoom = 1.0;
    const double maxZoom = 5.0;
    // 最小透明度提升到0.18，最大为0.85
    if (zoomLevel <= minZoom) return 0.18;
    if (zoomLevel >= maxZoom) return 0.85;
    return (0.18 + (zoomLevel - minZoom) / (maxZoom - minZoom) * (0.85 - 0.18)).clamp(0.18, 0.85);
  }

  void _drawMinorMarkers(Canvas canvas, Size size, DateTime startTime,
      Duration interval, TimeUnitConfig unit) {
    final double minorAlpha = _getMinorTickAlpha(manager.zoomLevel);
    if (minorAlpha < 0.01) return; // 透明度极低时不绘制
    final paint = Paint()
      ..color = Colors.grey[400]!.withOpacity(minorAlpha)
      ..strokeWidth = 1;

    // 计算次刻度数量
    final minorCount = _getMinorTickCount(unit);
    final minorInterval =
        Duration(milliseconds: interval.inMilliseconds ~/ minorCount);

    DateTime current = startTime;
    final endTime = manager.viewportEnd.add(interval);

    int iterations = 0;
    const maxIterations = 500;

    while (current.isBefore(endTime) && iterations < maxIterations) {
      for (int i = 1; i < minorCount; i++) {
        final minorTime = current
            .add(Duration(milliseconds: minorInterval.inMilliseconds * i));
        final x = manager.timeToX(minorTime, size.width);

        if (x >= 0 && x <= size.width) {
          // 只绘制下半部分次刻度线
          canvas.drawLine(
            Offset(x, size.height / 2),
            Offset(x, size.height / 2 + 12),
            paint,
          );
        }
      }
      current = _addInterval(current, interval, unit);
      iterations++;
    }
  }

  int _getMinorTickCount(TimeUnitConfig unit) {
    switch (unit.unit) {
      case TimeUnit.decade:
      case TimeUnit.year:
        return 5;
      case TimeUnit.month:
        return 4;
      case TimeUnit.day:
        return 6;
      case TimeUnit.hour:
        return 4;
      case TimeUnit.minute:
        return 6;
    }
  }

  DateTime _addInterval(DateTime time, Duration interval, TimeUnitConfig unit) {
    switch (unit.unit) {
      case TimeUnit.decade:
      case TimeUnit.year:
        final years = math.max(1, interval.inDays ~/ 365);
        return DateTime(time.year + years, time.month, time.day);

      case TimeUnit.month:
        final months = math.max(1, interval.inDays ~/ 30);
        var newMonth = time.month + months;
        var newYear = time.year;
        while (newMonth > 12) {
          newMonth -= 12;
          newYear++;
        }
        return DateTime(newYear, newMonth, time.day);

      default:
        return time.add(interval);
    }
  }

  void _drawEvents(Canvas canvas, Size size) {
    final visibleEvents = manager.getVisibleEvents();

    // 分为时间段事件和时间点事件
    final List<SpaxisEvent> rangeEvents = [];
    final List<SpaxisEvent> pointEvents = [];
    for (final event in visibleEvents) {
      if (event.endTime != null) {
        rangeEvents.add(event);
      } else {
        pointEvents.add(event);
      }
    }

    // 时间段事件：按优先级和时间排序，分配轨道
    rangeEvents.sort((a, b) {
      final priorityCompare = b.priority.compareTo(a.priority);
      if (priorityCompare != 0) return priorityCompare;
      return a.startTime.compareTo(b.startTime);
    });
    final trackAssignments = _assignEventTracks(rangeEvents, size.width);
    for (int i = 0; i < rangeEvents.length; i++) {
      final event = rangeEvents[i];
      final track = trackAssignments[event.id] ?? 0;
      _drawEvent(canvas, size, event, track);
    }

    // 时间点事件：全部绘制为圆点，不分轨道
    for (final event in pointEvents) {
      _drawPointEvent(canvas, size, event);
    }
  }



  // 新增：绘制时间点事件为圆点
  void _drawPointEvent(Canvas canvas, Size size, SpaxisEvent event) {
    final x = manager.timeToX(event.startTime, size.width);
    final centerY = size.height / 2;
    final distanceFromAxis = 60.0;
    final dotY = centerY + distanceFromAxis + size.height / 30 / 2 + 2;
    final diameter = size.height / 30;
    // 时间点事件始终完全显示，不参与模糊机制
    final double alpha = 1.0;
    final paint = Paint()
      ..color = event.color.withOpacity(alpha * 0.85)
      ..style = PaintingStyle.fill;
    final strokePaint = Paint()
      ..color = event.color.withOpacity(alpha * 1.0)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;
    canvas.drawCircle(Offset(x, dotY), diameter / 2, paint);
    canvas.drawCircle(Offset(x, dotY), diameter / 2, strokePaint);
    // 基于缩放级别和距离动态显示标题
    if (manager.zoomLevel > 5 && alpha > 0.6) {
      final textStyle = TextStyle(
        color: Color(0xFF8B4513).withOpacity(alpha), // 棕色字体
        fontSize: 10,
        fontWeight: FontWeight.w600,
        shadows: [Shadow(color: Colors.black26, blurRadius: 1)],
      );
      final textPainter = TextPainter(
        text: TextSpan(text: event.title, style: textStyle),
        textDirection: ui.TextDirection.ltr,
        maxLines: 1,
      );
      textPainter.layout(maxWidth: diameter * 3);
      textPainter.paint(
        canvas,
        Offset(x - textPainter.width / 2, dotY + diameter / 2 + 2),
      );
    }
  }

  // 改进的事件绘制方法
  void _drawEvent(Canvas canvas, Size size, SpaxisEvent event, int track) {
    final startX = manager.timeToX(event.startTime, size.width);
    final endX = event.endTime != null
        ? manager.timeToX(event.endTime!, size.width)
        : startX + math.max(20, 80 * manager.zoomLevel);
    final width = (endX - startX).abs();
    final alpha = TimelineUtils.eventAlpha(width, size.width);
    if (alpha < 0.01) return;
    final trackHeight = TimelineUtils.calcTrackHeight(size.height, trackCount);
    final y = TimelineUtils.calcTrackY(size.height, track, trackCount);
    final eventColor = event.color.withOpacity(alpha * 0.85);
    final paint = Paint()
      ..color = eventColor
      ..style = PaintingStyle.fill;
    final strokePaint = Paint()
      ..color = event.color.withOpacity(math.min(1.0, alpha + 0.2))
      ..style = PaintingStyle.stroke
      ..strokeWidth = 0.0;
    final leftBound = math.max(-50, startX);
    final rightBound = math.min(size.width + 50, endX);
    final rect = Rect.fromLTRB(
      leftBound.toDouble(),
      y,
      rightBound.toDouble(),
      y + trackHeight,
    );
    if (rect.right < 0 || rect.left > size.width) {
      return;
    }
    if (rightBound > leftBound && rightBound - leftBound > 5) {
      final cornerRadius =
          math.max(4.0, 8.0 * math.sqrt(manager.zoomLevel).clamp(0.5, 2.0));
      final rrect =
          RRect.fromRectAndRadius(rect, Radius.circular(cornerRadius));
      final shadowPaint = Paint()
      ..color = Colors.black.withOpacity(0.1 * alpha)
      ..maskFilter = MaskFilter.blur(BlurStyle.normal, 2);
    canvas.drawRRect(rrect.shift(Offset(2, 2)), shadowPaint);

    canvas.drawRRect(rrect, paint);

    canvas.drawRRect(rrect, strokePaint);
      // 动态显示事件标题和描述
      final minWidthForText = 30;
      if (rect.width > minWidthForText) {
        // 基于透明度和缩放级别调整字体大小
        final fontSize = math.max(
          9.0, 
          12.0 * math.sqrt(manager.zoomLevel).clamp(0.7, 1.5) * alpha
        );
        final textStyle = TextStyle(
          color: TimelineUtils.contrastColor(eventColor).withOpacity(alpha),
          fontSize: fontSize,
          fontWeight: FontWeight.w600,
          shadows: [Shadow(color: Colors.black26, blurRadius: 1)],
        );
        // 当事件框足够宽且透明度足够高时才显示标题
        if (rect.width > 50 && alpha > 0.4) {
          final textPainter = TextPainter(
            text: TextSpan(text: event.title, style: textStyle),
            textDirection: ui.TextDirection.ltr,
            maxLines: 1,
            ellipsis: '...',
          );
          final maxTextWidth = rect.width - 12;
          textPainter.layout(maxWidth: maxTextWidth);
          final visibleLeft = math.max(rect.left, 0.0);
          final visibleRight = math.min(rect.right, size.width);
          final visibleWidth = visibleRight - visibleLeft;
          double centerX;
          if (visibleWidth >= textPainter.width + 8) {
            centerX = (visibleLeft + visibleRight) / 2;
          } else {
            centerX = rect.left + rect.width / 2;
          }
          final textY = rect.top + (rect.height - textPainter.height) / 2;
          textPainter.paint(
            canvas,
            Offset(centerX - textPainter.width / 2, textY),
          );
        }
        // 当缩放级别足够高且事件框足够大时才显示描述
        if (manager.zoomLevel > 8 && rect.height > 40 && rect.width > 100 && alpha > 0.6) {
          _drawEventDetails(canvas, rect, event, alpha);
        }
      }
    }
  }

  // 改进的事件详情绘制
  void _drawEventDetails(Canvas canvas, Rect rect, SpaxisEvent event, double alpha) {
    if (event.description.isEmpty) return;
    final detailStyle = TextStyle(
      color: TimelineUtils.contrastColor(event.color).withOpacity(alpha * 0.8),
      fontSize: 9 * math.min(1.2, manager.zoomLevel / 10),
      fontWeight: FontWeight.normal,
    );
    final detailPainter = TextPainter(
      text: TextSpan(text: event.description, style: detailStyle),
      textDirection: ui.TextDirection.ltr,
      maxLines: 2,
      ellipsis: '...',
    );
    detailPainter.layout(maxWidth: rect.width - 12);
    detailPainter.paint(
      canvas,
      Offset(rect.left + 6, rect.bottom - detailPainter.height - 4),
    );
  }

  void _drawCurrentTimeIndicator(Canvas canvas, Size size) {
    final now = DateTime.now();
    final x = manager.timeToX(now, size.width);

    if (x >= -10 && x <= size.width + 10) {
      // 绘制主指示线
      final paint = Paint()
        ..color = Colors.red[600]!
        ..strokeWidth = 3;

      canvas.drawLine(
        Offset(x, 0),
        Offset(x, size.height),
        paint,
      );

      // 绘制顶部标记
      final trianglePaint = Paint()
        ..color = Colors.red[600]!
        ..style = PaintingStyle.fill;

      final trianglePath = Path();
      trianglePath.moveTo(x, 0);
      trianglePath.lineTo(x - 8, 16);
      trianglePath.lineTo(x + 8, 16);
      trianglePath.close();

      canvas.drawPath(trianglePath, trianglePaint);

      // 绘制"现在"标签
      final textStyle = TextStyle(
        color: Colors.red[700],
        fontSize: 12,
        fontWeight: FontWeight.bold,
      );

      final textPainter = TextPainter(
        text: TextSpan(text: '现在', style: textStyle),
        textDirection: ui.TextDirection.ltr,
      );
      textPainter.layout();

      // 标签背景
      final labelRect = Rect.fromCenter(
        center: Offset(x, 30),
        width: textPainter.width + 8,
        height: textPainter.height + 4,
      );

      final bgPaint = Paint()
        ..color = Colors.white.withOpacity(0.9)
        ..style = PaintingStyle.fill;

      canvas.drawRRect(
        RRect.fromRectAndRadius(labelRect, Radius.circular(4)),
        bgPaint,
      );

      textPainter.paint(
        canvas,
        Offset(x - textPainter.width / 2, 22),
      );
    }
  }

  @override
  bool shouldRepaint(TimelinePainter oldDelegate) {
    return true;
  }
}

// 命中事件结构体，供点击判定用
class HitEvent {
  final SpaxisEvent event;
  final double alpha;
  HitEvent(this.event, this.alpha);
}

// 工具类：轨道高度、Y轴、透明度、对比色等
class TimelineUtils {
  static double calcTrackHeight(double canvasHeight, int trackCount) {
    final t = trackCount.clamp(1, 5);
    return canvasHeight / (9 + t);
  }
  static double calcTrackY(double canvasHeight, int track, int trackCount) {
    final trackHeight = calcTrackHeight(canvasHeight, trackCount);
    final trackSpacing = trackHeight + 5;
    final maxVisibleTracks = ((canvasHeight * 0.6) / trackSpacing).floor();
    if (track >= maxVisibleTracks) return -99999;
    final centerY = canvasHeight / 2;
    final distanceFromAxis = 50.0;
    return centerY - distanceFromAxis - trackHeight - (track * trackSpacing);
  }
  static double eventAlpha(double width, double canvasWidth) {
    final ratio = width / canvasWidth;
    const minRatio = 0.2, maxRatio = 1.0, centerRatio = 1.0 / 3.0, minAlpha = 0.7, maxAlpha = 1.0;
    double alpha;
    if (ratio < minRatio) {
      alpha = minAlpha - (minRatio - ratio) * 3.0;
    } else if (ratio > maxRatio) {
      alpha = minAlpha - (ratio - maxRatio) * 2.5;
    } else if (ratio < centerRatio) {
      alpha = minAlpha + (maxAlpha - minAlpha) * (ratio - minRatio) / (centerRatio - minRatio);
    } else {
      alpha = maxAlpha - (maxAlpha - minAlpha) * (ratio - centerRatio) / (maxRatio - centerRatio);
    }
    return alpha.clamp(0.0, 1.0);
  }
  static Color contrastColor(Color backgroundColor) {
    final luminance = backgroundColor.computeLuminance();
    return luminance > 0.5 ? Colors.black87 : Colors.white;
  }
}

// TimelineCanvasStateHelper 用于静态方法复用
class TimelineCanvasStateHelper {
  static double calcTrackHeight(double canvasHeight, int trackCount) {
    final trackCountForHeight = trackCount.clamp(1, 5);
    switch (trackCountForHeight) {
      case 1:
        return canvasHeight / 10;
      case 2:
        return canvasHeight / 11;
      case 3:
        return canvasHeight / 12;
      case 4:
        return canvasHeight / 13;
      case 5:
        return canvasHeight / 14;
      default:
        return canvasHeight / 10;
    }
  }
  static double calcTrackY(double canvasHeight, int track, int trackCount) {
    final trackHeight = calcTrackHeight(canvasHeight, trackCount);
    final trackSpacing = trackHeight + 5;
    final maxVisibleTracks = ((canvasHeight * 0.6) / trackSpacing).floor();
    if (track >= maxVisibleTracks) return -99999;
    final centerY = canvasHeight / 2;
    final distanceFromAxis = 50.0;
    return centerY - distanceFromAxis - trackHeight - (track * trackSpacing);
  }
}

// 时间单位枚举
enum TimeUnit {
  decade, // 10年
  year, // 1年
  month, // 月
  day, // 日
  hour, // 时
  minute, // 分
}